
#include <stdio.h>
#include <nds.h>
#include <fat.h>
#include <nds/system.h>
#include <nds/arm9/image.h>
#include <malloc.h>
#include <maxmod9.h>
#include <math.h>

#include "Block.h"
#include "Inventory.h"
#include "GUIManager.h"
#include "RenderBlock.h"
#include "Player.h"
#include "Sounds.h"
#include "TextureManager.h"
#include "VideoInit.h"
#include "WorldGenerator.h"
#include "World.h"

int ID = 256, MIN_ID = 1, MAX_ID;
float	xrot, yrot, zrot;
float	xmove, ymove, zmove;
touchPosition lastTouch, touch;
int mode;
long secTime, lastTime;
bool repeat;

void DrawGLScene()
{
	glLoadIdentity();

	glRotatef(xrot,1.0f,0.0f,0.0f);
	glRotatef(yrot,0.0f,1.0f,0.0f);
	glRotatef(zrot,0.0f,0.0f,1.0f);

	renderWorld();
}

void updateGUI() {
	scanKeys();
	touchRead(&touch);
	if(guiMode == GUI_INVENTORY) {

		int field = clickedField(touch.px, touch.py);
		if(field != -1) {
			if(getBlockWith(slots[field]) != 0) {
				int idsave = ID;
				ID = slots[field];
				if(ID != idsave) {
					int j = getBlockWith(ID)->getTextureFrom(0);
					draw2DQuad(oamSub, 0, 10, 10, j%16, j/16);
				}
			}
		}

		if(keysDown() & KEY_START) {
			setGUI(GUI_INGAME);
		}

	} else {
		setGUI(GUI_INGAME);
	}
}

void update() {
	if(!isInGame()) {
		updateGUI();
	} else {

	secTime++;

	float angleXZ2 = (float) (((yrot+270)/180) * (M_PI));
	float angleY = (float) (((180-xrot)/180) * (M_PI));

	scanKeys();
	if(keysDown()) {
		int idsave = ID;
		if(keysDown() & KEY_A) ID++;
		if(keysDown() & KEY_B) ID--;
		if(ID < MIN_ID) ID = MAX_ID;
		if(ID > MAX_ID) ID = MIN_ID;
		if(ID != idsave) {
			int j = getBlockWith(ID)->getTextureFrom(0);
			draw2DQuad(oamSub, 0, 10, 10, j%16, j/16);
		}

		if(keysDown() & KEY_Y) {
			mode++;
			if(mode > 1) mode = 0;
		}

		if(keysDown() & KEY_TOUCH) {
			touchRead(&lastTouch);
			if(ymove == 0 && repeat && int(secTime-lastTime) < 5) {
				jump();
				repeat = false;
			} else {
				repeat = true;
			}
			lastTime = secTime;
		}

		if((keysDown() & KEY_L) || (keysDown() & KEY_R)) {
			if(mode == 0) { // Destroy
				setBlockId(selectedX, selectedY, selectedZ, 0);
			} else
			if(mode == 1) { // Build
				int x = (int) (posX + cos(angleXZ2)*(selectedD-0.1) + (SHOW_X/2));
				int y = (int) (posY + tan(angleY)*(selectedD-0.1) + (SHOW_Y/2));
				int z = (int) (posZ + sin(angleXZ2)*(selectedD-0.1) + (SHOW_Z/2));
				if(getBlockId(x, y, z) == 0) {
					setBlockId(x, y, z, ID);
				}
			}
		}

		if(keysDown() & KEY_START) {
			setGUI(GUI_INVENTORY);
		}
	}

	if(keysHeld()) {
		float angleLR = (((yrot)/180) * (M_PI));
		float angleUD = (((yrot+90)/180) * (M_PI));

		if(keysHeld() & KEY_LEFT) {
			xmove=-(speed*cos(angleLR));
			zmove=-(speed*sin(angleLR));
		}
		if(keysHeld() & KEY_RIGHT) {
			xmove=(speed*cos(angleLR));
			zmove=(speed*sin(angleLR));
		}
		if(keysHeld() & KEY_UP) {
			xmove=-(speed*cos(angleUD));
			zmove=-(speed*sin(angleUD));
		}
		if(keysHeld() & KEY_DOWN) {
			xmove=(speed*cos(angleUD));
			zmove=(speed*sin(angleUD));
		}

		if(keysHeld() & KEY_TOUCH) {
			touchRead(&touch);

			int rx = (touch.px - lastTouch.px);
			int ry = (touch.py - lastTouch.py);

			xrot += ry;
			if(xrot < -90.0f) xrot = -90.0f;
			if(xrot > 90.0f) xrot = 90.0f;
			yrot += rx;

			lastTouch = touch;
		}
	}

	for(float d = 0; d < 8; d+=0.1f) {
		selectedD = d;
		selectedX = (int) (posX + cos(angleXZ2)*d + (SHOW_X/2));
		selectedY = (int) (posY + tan(angleY)*d + (SHOW_Y/2));
		selectedZ = (int) (posZ + sin(angleXZ2)*d + (SHOW_Z/2));
		if(getBlockId(selectedX, selectedY, selectedZ) != 0) break;
	}

	move(xmove, ymove, zmove);
	scrollWorld(&posX, &posY, &posZ);
	}
}

void render() {
	glPushMatrix();

	DrawGLScene();

	glFlush(0);

	oamUpdate(&oamMain);
	oamUpdate(&oamSub);
}

int main() {
	int i = MIN_ID;
	while(getBlockWith(i) != 0 && i < 255) {
		i++;
	}
	MAX_ID = i-1;

	initVideoMode();

	lcdMainOnBottom();

	LoadGLTextures();

	openGLPerspectiveInit();
	openGLMaterialInit();
	openGLLightInit();

	createWorld(128, 48, 128);
	generateWorld();
	fillInventory();
	drawInventory();
	setPosition((WORLD_WIDTH)/2, (WORLD_HEIGHT), (WORLD_DEPTH)/2);
	consoleClear();

	while(true)
	{
		update();

		render();

		swiWaitForVBlank();
	}

	return 0;
}
